<template>
	<div id="map"></div>
</template>

<script setup>
import { createScene } from '@/three/system/createScene.js';
import { createCamera } from '@/three/system/createCamera.js';
import { createRenderer } from '@/three/system/createRenderer.js';
import { createLoop } from '@/three/system/createLoop.js';
import { createControl } from '@/three/system/createControl.js';
import { createLabelRenderer } from '@/three/system/createLabelRenderer';
import { onMounted, reactive } from 'vue';
import { getMapData } from './api/common.js';
import * as THREE from 'three';
import { createMapBorder, setCenter } from './three/createMap.js';
import { geoMercator } from 'd3';
import chinaMap from './map/china.json';
import chinaMapAll from './map/china_all.json';
import offsetXY from './three/utils/offsetXY.js';
const data = reactive({
	mapAdCode: 100000,
	// mapAdCode: 510000,
	mapData: {},
});
const queryMapData = () => {
	getMapData(data.mapAdCode).then((res) => {
		// data.mapData = res.data;
		data.mapData = chinaMapAll;
		console.log('mapData:', data.mapData);
		initMap();
	});
};
const initMap = () => {
	const mapRef = document.getElementById('map');
	const scene = createScene();
	window.scene = scene;
	const camera = createCamera();
	const renderer = createRenderer(mapRef, scene, data.mapData);
	const controls = createControl(camera, renderer);
	const labelRenderer = createLabelRenderer(mapRef);

	const axesHelper = new THREE.AxesHelper(100);
	scene.add(axesHelper);

	const size = 200;
	const divisions = 100;

	// const gridHelper = new THREE.GridHelper(size, divisions);
	// scene.add(gridHelper);

	const cameraHelper = new THREE.CameraHelper(camera);
	scene.add(cameraHelper);

	let borderCB = mapBorderFn(scene);

	let { x, y, z } = scene.getObjectByName('border').position;
	scene.getObjectByName('map').position.set(x, y, z);
	// scene.getObjectByName('map').position.set(0, 0, 0);
	const loop = createLoop(
		scene,
		camera,
		renderer,
		controls,
		labelRenderer,
		(adcode) => {
			data.mapAdCode = adcode;
			queryMapData();
		},
		{
			borderCB,
		}
	);
};

const mapBorderFn = (scene) => {
	const border = createMapBorder(chinaMap);
	scene.add(border);
	let lines = [];
	let {
		properties: { center },
		geometry,
	} = chinaMap.features[0];
	let { coordinates } = geometry;
	coordinates[0].forEach((item) => {
		item.forEach((v) => {
			// const projectionFn = geoMercator();
			let [x, y] = offsetXY(v);
			lines.push([x, -y, 0]);
		});
	});

	// 炫光粒子 透明度
	let opacitys = [];
	// 炫光粒子 几何体
	const geometryLz = new THREE.BufferGeometry();
	// 拉平 为一维数组
	const positions = new Float32Array(lines.flat(1));
	// 设置顶点
	geometryLz.setAttribute('position', new THREE.BufferAttribute(positions, 3));
	// 设置 粒子透明度为 0
	opacitys = new Float32Array(positions.length).map(() => 0);
	geometryLz.setAttribute('aOpacity', new THREE.BufferAttribute(opacitys, 1));

	geometryLz.currentPos = 30;
	// 炫光移动速度
	geometryLz.pointSpeed = 10;

	// 控制 颜色和粒子大小
	const params = {
		pointSize: 2.0,
		pointColor: '#4ec0e9',
	};

	/**
	 * 定义 着色器
	 **/
	const vertexShader = `
                      attribute float aOpacity;
                      uniform float uSize;
                      varying float vOpacity;

                      void main(){
                          gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);
                          gl_PointSize = uSize;

                          vOpacity=aOpacity;
                      }
                            `;
	const fragmentShader = `
                      varying float vOpacity;
                      uniform vec3 uColor;

                      float invert(float n){
                          return 1.-n;
                      }

                      void main(){
                        if(vOpacity <=0.2){
                            discard;
                        }
                        vec2 uv=vec2(gl_PointCoord.x,invert(gl_PointCoord.y));
                        vec2 cUv=2.*uv-1.;
                        vec4 color=vec4(1./length(cUv));
                        color*=vOpacity;
                        color.rgb*=uColor;

                        gl_FragColor=color;
                      }
                      `;

	// 创建着色器材质
	const material = new THREE.ShaderMaterial({
		vertexShader: vertexShader,
		fragmentShader: fragmentShader,
		transparent: true, // 设置透明
		uniforms: {
			uSize: {
				value: params.pointSize,
			},
			uColor: {
				value: new THREE.Color(params.pointColor),
			},
		},
	});
	const points = new THREE.Points(geometryLz, material);
	setCenter(points);
	let { x, y, z } = scene.getObjectByName('border').position;
	points.position.set(x, y + 1.2, z);
	// points.scale.set(1.001, 1.001, 1.001);
	scene.add(points);
	return () => {
		if (geometryLz.attributes.position) {
			geometryLz.currentPos += geometryLz.pointSpeed;
			for (let i = 0; i < geometryLz.pointSpeed; i++) {
				opacitys[(geometryLz.currentPos - i) % lines.length] = 0;
			}

			for (let i = 0; i < 200; i++) {
				opacitys[(geometryLz.currentPos + i) % lines.length] = i / 50 > 2 ? 2 : i / 50;
			}
			geometryLz.attributes.aOpacity.needsUpdate = true;
		}
	};
};

onMounted(() => {
	queryMapData();
});
</script>

<style>
#map {
	background-color: #d4e7fd;
}
</style>
